﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>函数对象 - 定义 &amp; 使用 | AutoHotkey v2</title>
<meta name="description" content="Function objects are either references to 检索函数 objects representing actual functions, or objects which can be called like functions." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
<script type="text/javascript">$(function(){0<=window.navigator.userAgent.toLowerCase().indexOf("ucbrowser")&&CaoNiMaDeUc()})</script>
</head>
<body>

<h1>函数对象</h1>

<p>"函数对象" 通常表示以下任何一项:</p>
<ul>
  <li><a href="Func.htm">检索函数</a> 或 <a href="../Functions.htm#closures">Closure</a> 对象, 它表示一个实际的<a href="../Functions.htm">函数</a>; 可以是内置函数也可以是脚本定义的函数.</li>
  <li>用户定义的对象, 可以像函数一样调用. 亦称为"函数子".</li>
  <li>任何其他可以像函数一样调用的对象, 如<a href="#BoundFunc">绑定函数对象</a>或 COM 方法返回的 JavaScript 函数对象.</li>
</ul>
<p>函数对象可用于以下情况:</p>
<ul>
  <li><a href="GuiOnEvent.htm">界面 事件</a></li>
  <li><a href="../commands/Hotkey.htm">热键</a></li>
  <li><a href="Menu.htm#Add">Menu.Add</a></li>
  <li><a href="../commands/OnClipboardChange.htm">在剪贴板内容改变时</a></li>
  <li><a href="../commands/OnExit.htm">在退出时</a></li>
  <li><a href="../commands/OnMessage.htm">在收到消息时</a></li>
  <li><a href="../commands/SetTimer.htm">设置定时器</a></li>
</ul>

<h2 id="User-Defined">用户自定义</h2>
<!-- TODO: Explain how a user-defined 对象 could be useful -->
<p>用户定义的函数对象必须包含一个 "函数" 实现的 <em>Call</em> 方法定义.</p>
<pre>class YourClassName {
    Call(a, b) {  <em>; 按需声明参数, 或 <a href="../Functions.htm#Variadic">数组*</a>.</em>
        <em>;...</em>
        返回 c
    }
    <em>;...</em>
}
</pre>
<h3 id="User-Defined-Examples">示例</h3>
<p>下面的例子定义了一个可以被调用的函数数组; 当被调用时, 它依次调用数组中的每个元素.</p>
<pre>class FuncArrayType extends 数组 {
    Call(params*) {
        <em>; 调用函数列表.</em>
        循环 this.Length
            %this[内_循环次数]%(params*)
    }
}

<em>; 创建一个函数数组.</em>
funcArray := FuncArrayType.new()
<em>; 向数组中添加函数(可以在任何位置完成).</em>
funcArray.Push(检索函数("One"))
funcArray.Push(检索函数("Two"))
<em>; 创建一个使用数组作为方法的对象.</em>
obj := {}
obj.DefineMethod("method", funcArray)
<em>; 调用方法.</em>
%obj.method%("foo", "bar")

One(param1, param2) {
    变量列表
    信息框
}
Two(param1, param2) {
    变量列表
    信息框
}</pre>

<h2 id="BoundFunc">绑定函数对象</h2>
<p>行为像函数, 但只是将预定义的参数传递给另一个函数.</p>
<p>有两种建立绑定函数对象的方式:</p>
<ul>
  <li>通过调用 <a href="Func.htm#Bind">检索函数.Bind</a> 方法, 其绑定参数值至一个函数.</li>
  <li>通过调用 <a href="../commands/ObjBindMethod.htm">对象绑定方法</a> 函数, 其绑定参数值和方法名至目标对象.</li>
</ul>
<p>可以调用绑定函数对象, 如下例所示. 当绑定函数对象被调用时, 它调用绑定的函数或方法, 传递绑定的参数和后面跟着的调用者传递的任何参数. 未绑定的参数位置是从调用者的参数列表中指定的位置(从左到右). 例如:</p>
<pre>fn := 检索函数("RealFn").Bind(1)  <em>; 只绑定第一个参数</em>
%fn%(2)    <em>; 显示 "1, 2"</em>
fn.Call(3) <em>; 显示 "1, 3"</em>

fn := 检索函数("RealFn").Bind( , 1)  <em>; 只绑定第二个参数</em>
%fn%(2)    <em>; 显示 "2, 1"</em>
fn.Call(3) <em>; 显示 "3, 1"</em>
%fn%(, 4)  <em>; 错误: 'a' 被省略了</em>

RealFn(a, b, c:="c") {
    信息框 a ", " b
}</pre>
<p><a href="../commands/ObjBindMethod.htm">对象绑定方法</a> 可用于绑定方法, 即使是在无法检索到方法本身的引用时. 例如:</p>
<pre>file := 打开文件(内_脚本全路径, "r")
getLine := 对象绑定方法(file, "ReadLine")
信息框 %getLine%()  <em>; 显示此文件的第一行.</em></pre>
<p>更多复杂的例子, 请参阅 <a href="../commands/SetTimer.htm#ExampleClass">设置定时器</a>.</p>
<p>其他的属性和方法都是从 <a href="Func.htm">检索函数</a> 继承过来的, 但不反映目标函数或方法的属性(不需要作为一个函数来实现). BoundFunc 作为一个匿名的变量函数, 没有其他形式上的参数, 类似于下面的<a href="../Variables.htm#fat-arrow">胖箭头函数</a>:</p>
<pre>Func_Bind(检索函数, bound_args*) {
    返回 (args*) => (args.InsertAt(1, bound_args*), %检索函数%(args*))
}</pre>

</body>
</html>